/*
 * Copyright (C) 2013 Daniel Wasilew <daniel.wasilew@codeminer.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.codeminer.parts;

import org.apache.log4j.PropertyConfigurator;
import org.codeminer.parts.application.Application;
import org.codeminer.parts.application.ApplicationContext;
import org.codeminer.parts.database.derby.DerbyDatabaseManager;
import org.codeminer.parts.server.ActionHandler;
import org.codeminer.parts.server.DefaultWebApplication;
import org.codeminer.parts.server.RestServer;
import org.codeminer.parts.server.permissions.DefaultPermissionManager;
import org.codeminer.parts.server.users.DatabaseUserManager;
import org.codeminer.parts.settings.Settings;
import org.codeminer.parts.update.PeriodicUpdateChecker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * @author Daniel Wasilew <daniel.wasilew@codeminer.org>
 */
public final class PartsStart {

    private static Logger log = LoggerFactory.getLogger(PartsStart.class);
    private static ApplicationContext applicationContext;

    private static File getBaseDir(String dirToCreate) {
        File dir;
        if (applicationContext.isDevelopment()) {
            dir = new File("data/" + dirToCreate);
        } else {
            dir = new File("/media/data/" + dirToCreate);
        }
        return dir;
    }

    private static void initializeFolderStructure() {
        log.trace("[START] initializing directory structure");
        applicationContext.setBaseDir(new File(""));

        File libraryDir = createDir("library");
        applicationContext.setLibraryFolder(libraryDir);

        File artworkDir = createDir("artworks");
        applicationContext.setArtworkFolder(artworkDir);

        File configurationDir = createDir("configuration");
        applicationContext.setConfigurationDir(configurationDir);

        File tmpDir = createDir("tmp");
        applicationContext.setTmpDir(tmpDir);

        File helpDir = applicationContext.isDevelopment() ? new File("src/main/resources/documents") : createDir("bin/help");
        applicationContext.setHelpDir(helpDir);

        File databaseDir = getBaseDir("parts-db");
        log.info("setting databasedir to [{}]", databaseDir);
        applicationContext.setDatabaseDir(databaseDir);

        File databaseScriptDir = applicationContext.isDevelopment() ? new File("src/main/resources/sql") : createDir("bin/sql");
        applicationContext.setDatabaseScriptDir(databaseScriptDir);

        log.trace("[FINISHED] initializing directory structure");
    }

    private static File createDir(String dirToCreate) {
        File dir = getBaseDir(dirToCreate);

        if (!dir.exists()) {
            log.trace("creating directory [{}]", dir.getAbsolutePath());
            dir.mkdirs();
            log.trace("checking directory [{}] -> {}", dir.getAbsolutePath(), dir.exists());
            if (!dir.exists()) {
                log.error("directory could not be created");
            }
        }

        return dir;
    }

    public static void main(String[] args) {
        initializeLogger(PathUtil.isDevelopment());

        log.info("starting parts-server");
        applicationContext = new ApplicationContext();
        applicationContext.setDevelopment(PathUtil.isDevelopment());
        Application manager = new Application();

        applicationContext.setApplication(manager);

        initializeFolderStructure();

        manager.addApplicationComponent(new Settings());
        manager.addApplicationComponent(new DerbyDatabaseManager());
        manager.addApplicationComponent(new DatabaseUserManager());
        manager.addApplicationComponent(new DefaultPermissionManager());
        manager.addApplicationComponent(new ActionHandler());
        manager.addApplicationComponent(new DefaultWebApplication());
        manager.addApplicationComponent(new RestServer());
        manager.addApplicationComponent(new PeriodicUpdateChecker());
        try {
            manager.startup(applicationContext);
        } catch (Exception ex) {
            log.error("error while starting application. this is not good", ex);
        }
    }

    private static void initializeLogger(boolean isDevelopment) {
        if (!isDevelopment) {
            try {
                Properties logProperties = new Properties();
                InputStream deploymentInputStream = PartsStart.class.getResourceAsStream("/deployment-logging.properties");
                logProperties.load(deploymentInputStream);
                PropertyConfigurator.configure(logProperties);
            } catch (IOException ex) {
                log.error("could not read deployment-properties", ex);
            }
        }
    }
}
